#include "stdafx.h"
#include "DataManager.h"
#include "SymbolInfo.h"
#include "AccountInfo.h"
#include "OptionStrikes.h"
#include "GomSymbolReceiver.h"
#include "SPUtil.h"
#include "GomChartReceiver.h"
#include "ChartData.h"
#include "ChartMultiData.h"
#include "ChartSingleData.h"
#include <algorithm>
#include "FdbData.h"
#include "Global.h"
#include "linear.h"
#include <ta_func.h>



CDataManager::CDataManager()
	: m_MonoWaves(m_PriceNodes)
	, m_PriceNodeInterval(0)
	, m_PriceNodesPerInterval(1)
	, m_PriceNodeIntervalRaw(0)
{
	m_PriceNodesRaw.reserve(20000);
	m_PriceNodes.reserve(20000);
}


CDataManager::~CDataManager()
{
	for (OptionMonthMapPos pos = m_OptionMonthMap.begin(); pos != m_OptionMonthMap.end(); ++pos)
	{
		OptionMonth* curMon = pos->second;

		mapOptionStrike strikes = curMon->mapStrikes;

		for (OptionStrikeMapPos pos = strikes.begin(); pos != strikes.end(); ++pos)
		{
			OptionStrike* curStrike = pos->second;
			delete curStrike;
			curStrike = NULL;
		}

		strikes.clear();

		delete curMon;
		curMon = NULL;
	}

	m_OptionMonthMap.clear();

	for (AccountInfoPos pos = AccountMap.begin(); pos != AccountMap.end(); ++pos)
	{
		CAccountInfo* curAcc = pos->second;
		delete curAcc;
		curAcc = NULL;
	}

	AccountMap.clear();

	for (SymbolInfoPos pos = SymbolMap.begin(); pos != SymbolMap.end(); ++pos)
	{
		CSymbolInfo* curSym = pos->second;
		delete curSym;
		curSym = NULL;
	}

	SymbolMap.clear();


	for (GomSymRcvrPos pos = mapGomSym.begin(); pos != mapGomSym.end(); ++pos)
	{
		CGomSymbolReceiver* curSym = pos->second;
		delete curSym;
		curSym = NULL;
	}

	mapGomSym.clear();


	for (GomChartListPos pos = GChartList.begin(); pos != GChartList.end(); ++pos)
	{
		CGomChartReceiver* curSym = *pos;
		curSym->UnadviseEvent();
		delete curSym;
		curSym = NULL;
	}

	GChartList.clear();
	
	for (ChartDataListColPos pos = CDLCol.begin(); pos != CDLCol.end(); ++pos)
	{
		ChartDataList* curSym = *pos;
		for (ChartDataListPos pos2 = curSym->begin(); pos2 != curSym->end(); ++pos2)
		{
			CChartData* curData = *pos2;
			delete curData;
			curData = NULL;
		}
		curSym->clear();

		delete curSym;
		curSym = NULL;
	}

	CDLCol.clear();
	

	for (mapChartDataListPos pos = ChartDataListMap.begin(); pos != ChartDataListMap.end(); ++pos)
	{
		ChartDataList* curSym = pos->second;
		for (ChartDataListPos pos2 = curSym->begin(); pos2 != curSym->end(); ++pos2)
		{
			CChartData* curData = *pos2;
			delete curData;
			curData = NULL;
		}
		curSym->clear();

		delete curSym;
		curSym = NULL;
	}

	ChartDataListMap.clear();


	for (mapChartDataListPos pos = RealTimeDataMap.begin(); pos != RealTimeDataMap.end(); ++pos)
	{
		ChartDataList* curSym = pos->second;
		for (ChartDataListPos pos2 = curSym->begin(); pos2 != curSym->end(); ++pos2)
		{
			CChartData* curData = *pos2;
			delete curData;
			curData = NULL;
		}
		curSym->clear();

		delete curSym;
		curSym = NULL;
	}

	RealTimeDataMap.clear();


	for (mapChartDataListPos pos = ElaboratedDataMap.begin(); pos != ElaboratedDataMap.end(); ++pos)
	{
		ChartDataList* curSym = pos->second;
		for (ChartDataListPos pos2 = curSym->begin(); pos2 != curSym->end(); ++pos2)
		{
			CChartData* curData = *pos2;
			delete curData;
			curData = NULL;
		}
		curSym->clear();

		delete curSym;
		curSym = NULL;
	}

	RealTimeDataMap.clear();

	for (mapChartMultiDataPos pos = ChartMD.begin(); pos != ChartMD.end(); ++pos)
	{
		CChartMultiData* curSym = pos->second;
		delete curSym;
		curSym = NULL;
	}

	ChartMD.clear();

	for (mapChartSingleDataPos pos = ChartSD.begin(); pos != ChartSD.end(); ++pos)
	{
		CChartSingleData* curSym = pos->second;
		delete curSym;
		curSym = NULL;
	}

	ChartSD.clear();
}

CSymbolInfo* CDataManager::AddSymbolInfo(string a_SymBolCode)
{
	size_t size = SymbolMap.size();
	if (size == 0)
	{
		CSymbolInfo* symInfo = new CSymbolInfo();
		symInfo->m_Code = a_SymBolCode;
		SymbolMap.insert(pairSymbolInfo(a_SymBolCode, symInfo));
		return symInfo;
	}
	else
	{
		SymbolInfoPos pos = SymbolMap.find(a_SymBolCode);
		if (pos == SymbolMap.end())
		{
			CSymbolInfo* symInfo = new CSymbolInfo();
			symInfo->m_Code = a_SymBolCode;
			SymbolMap.insert(pairSymbolInfo(a_SymBolCode, symInfo));
			return symInfo;
		}
		else
		{
			return pos->second;
		}
	}
}

CAccountInfo* CDataManager::AddAccountInfo(string a_AccName, string a_HipendCode)
{
	size_t size = AccountMap.size();
	if (size == 0)
	{
		CAccountInfo* accInfo = new CAccountInfo();
		accInfo->Code = a_AccName.c_str();
		accInfo->HipenCode = a_HipendCode.c_str();
		AccountMap.insert(pairAccountInfo(a_AccName, accInfo));
		return accInfo;
	}
	else
	{
		AccountInfoPos pos = AccountMap.find(a_AccName);
		if (pos == AccountMap.end())
		{
			CAccountInfo* accInfo = new CAccountInfo();
			accInfo->Code = a_AccName.c_str();
			accInfo->HipenCode = a_HipendCode.c_str();
			AccountMap.insert(pairAccountInfo(a_AccName, accInfo));
			return accInfo;
		}
		else
		{
			return pos->second;
		}
	}
}

CSymbolInfo* CDataManager::FindSymbolInfo(string a_SymBolCode)
{
	SymbolInfoPos pos = SymbolMap.find(a_SymBolCode);
	if (pos == SymbolMap.end())
	{
		return NULL;
	}
	else
	{
		return pos->second;
	}
}

CAccountInfo* CDataManager::FindAccountInfo(string a_AccName)
{
	AccountInfoPos pos = AccountMap.find(a_AccName);
	if (pos == AccountMap.end())
	{
		return NULL;
	}
	else
	{
		return pos->second;
	}
}

CAccountInfo* CDataManager::FindAccountByHipenedCode(string a_AccCode)
{
	CAccountInfo* curAcc = NULL;
	for (AccountInfoPos pos = AccountMap.begin(); pos != AccountMap.end(); ++pos)
	{
		curAcc = pos->second;
		if (curAcc->HipenCode.compare(a_AccCode) == 0)
		return curAcc;
	}

	return NULL;
}

void CDataManager::AddTickInfo( CSymbolInfo* a_SymInfo )
{
	;
}

OptionMonth* CDataManager::AddOptionMonth(string a_MonthCode)
{
	size_t size = m_OptionMonthMap.size();
	if (size == 0)
	{
		OptionMonth* opMon = new OptionMonth();
		opMon->MonthCode = a_MonthCode;
		m_OptionMonthMap.insert(pairOptionMonth(a_MonthCode, opMon));
		return opMon;
	}
	else
	{
		OptionMonthMapPos pos = m_OptionMonthMap.find(a_MonthCode);
		if (pos == m_OptionMonthMap.end())
		{
			OptionMonth* opMon = new OptionMonth();
			opMon->MonthCode = a_MonthCode;
			m_OptionMonthMap.insert(pairOptionMonth(a_MonthCode, opMon));
			return opMon;
		}
		else
		{
			return pos->second;
		}
	}
}

OptionStrike* CDataManager::FindOptionStrike(string a_MonthCode, string a_StrikePrice)
{
	return NULL;
}

void CDataManager::AddWndInfo(HWND a_Wnd, WndInfo a_WndInfo)
{
	if (a_Wnd == NULL)
		return;
	WndInfoMap.insert(pairWndInfo(a_Wnd, a_WndInfo));
}

void CDataManager::EraseWndInfo(HWND a_Wnd)
{
	if (a_Wnd == NULL)
		return;
	posWndInfo pos = WndInfoMap.find(a_Wnd);
	if (pos != WndInfoMap.end())
	{
		WndInfoMap.erase(pos);
	}
}

bool CDataManager::IsFoundWndByAccount(string a_AccCode)
{
	for (posWndInfo pos = WndInfoMap.begin(); pos != WndInfoMap.end(); ++pos)
	{
		WndInfo wndInfo = pos->second;
		if (wndInfo.AccountCode.compare(a_AccCode) == 0)
		{
			return true;
		}
	}

	return false;
}

bool CDataManager::IsFoundWndBySymbol(string a_Symbol)
{
	for (posWndInfo pos = WndInfoMap.begin(); pos != WndInfoMap.end(); ++pos)
	{
		WndInfo wndInfo = pos->second;
		if (wndInfo.SymbolCode.compare(a_Symbol) == 0)
		{
			return true;
		}
	}

	return false;
}

void CDataManager::ChangeWndInfoByAccount(HWND a_Wnd, string a_AccCode)
{
	if (a_Wnd == NULL)
		return;
	posWndInfo pos = WndInfoMap.find(a_Wnd);
	if (pos != WndInfoMap.end())
	{
		(pos->second).AccountCode = a_AccCode;
	}
}

void CDataManager::ChangeWndInfoBySymbol(HWND a_Wnd, string a_Symbol)
{
	if (a_Wnd == NULL)
		return;
	posWndInfo pos = WndInfoMap.find(a_Wnd);
	if (pos != WndInfoMap.end())
	{
		(pos->second).SymbolCode = a_Symbol;
	}
}

void CDataManager::AddJangoDlg(HWND a_Wnd, string a_AccCode)
{
	if (a_Wnd == NULL)
		return;
	JangoDlgMap.insert(pairCodeWnd(a_Wnd, a_AccCode));
}

void CDataManager::EraseJangoDlg(HWND a_Wnd)
{
	if (a_Wnd == NULL)
		return;
	posCodeWnd pos = JangoDlgMap.find(a_Wnd);
	if (pos != JangoDlgMap.end())
	{
		JangoDlgMap.erase(pos);
	}
}

bool CDataManager::IsFoundJangoDlg(string a_AccCode)
{
	for (posCodeWnd pos = JangoDlgMap.begin(); pos != JangoDlgMap.end(); ++pos)
	{
		string accCode = pos->second;
		if (accCode.compare(a_AccCode) == 0)
		{
			return true;
		}
	}

	return false;
}

void CDataManager::ChangeJangoDlg(HWND a_Wnd, string a_AccCode)
{
	if (a_Wnd == NULL)
		return;
	posCodeWnd pos = JangoDlgMap.find(a_Wnd);
	if (pos != JangoDlgMap.end())
	{
		(pos->second) = a_AccCode;
	}
}

CGomSymbolReceiver* CDataManager::AddGomSymReceiver(string a_SymbolCode)
{
	size_t size = mapGomSym.size();
	if (size == 0)
	{
		CGomSymbolReceiver* symInfo = new CGomSymbolReceiver();
		symInfo->m_SymbolCode = a_SymbolCode;
		mapGomSym.insert(pairGomSymRcvr(a_SymbolCode, symInfo));
		return symInfo;
	}
	else
	{
		GomSymRcvrPos pos = mapGomSym.find(a_SymbolCode);
		if (pos == mapGomSym.end())
		{
			CGomSymbolReceiver* symInfo = new CGomSymbolReceiver();
			symInfo->m_SymbolCode = a_SymbolCode;
			mapGomSym.insert(pairGomSymRcvr(a_SymbolCode, symInfo));
			return symInfo;
		}
		else
		{
			return pos->second;
		}
	}
}

CGomSymbolReceiver* CDataManager::AddGomSymReceiver(CSymbolInfo* a_Symbol)
{
	if (a_Symbol == NULL)
		return NULL;

	string gomCode = CSPUtil::KRToGom(a_Symbol->m_Code);

	size_t size = mapGomSym.size();
	if (size == 0)
	{
		CGomSymbolReceiver* symInfo = new CGomSymbolReceiver();
		symInfo->m_SymbolCode = gomCode;
		symInfo->m_pSymbol = a_Symbol;
		mapGomSym.insert(pairGomSymRcvr(a_Symbol->m_Code, symInfo));
		return symInfo;
	}
	else
	{
		GomSymRcvrPos pos = mapGomSym.find(a_Symbol->m_Code);
		if (pos == mapGomSym.end())
		{
			CGomSymbolReceiver* symInfo = new CGomSymbolReceiver();
			symInfo->m_SymbolCode = gomCode;
			symInfo->m_pSymbol = a_Symbol;
			mapGomSym.insert(pairGomSymRcvr(a_Symbol->m_Code, symInfo));
			return symInfo;
		}
		else
		{
			return pos->second;
		}
	}
}

CGomChartReceiver* CDataManager::AddGomChart(string a_Code, IChartDataType a_DataType, IChartBaseType a_BaseType, long a_Period, long a_Count)
{
	CGomChartReceiver* chartMgr = new CGomChartReceiver();
	GChartList.push_back(chartMgr);
	chartMgr->Code(a_Code);
	chartMgr->DataType(a_DataType);
	chartMgr->BaseType(a_BaseType);
	chartMgr->Period(a_Period);
	chartMgr->Count(a_Count);
	return chartMgr;
}

ChartDataList* CDataManager::AddChartDataList(string a_Serial)
{
	size_t size = ChartDataListMap.size();
	if (size == 0)
	{
		ChartDataList* symInfo = new ChartDataList();
		ChartDataListMap.insert(pairChartDataList(a_Serial, symInfo));
		return symInfo;
	}
	else
	{
		mapChartDataListPos pos = ChartDataListMap.find(a_Serial);
		if (pos == ChartDataListMap.end())
		{
			ChartDataList* symInfo = new ChartDataList();
			ChartDataListMap.insert(pairChartDataList(a_Serial, symInfo));
			return symInfo;
		}
		else
		{
			return pos->second;
		}
	}
}

void CDataManager::ClearChartData(string a_CDListKey)
{
	mapChartDataListPos pos = ChartDataListMap.find(a_CDListKey);
	if (pos != ChartDataListMap.end())
	{
		ChartDataList* cdList = pos->second;
		for (ChartDataListPos pos2 = cdList->begin(); pos2 != cdList->end(); ++pos2)
		{
			CChartData* curData = *pos2;
			delete curData;
			curData = NULL;
		}
		cdList->clear();
	}
}

ChartDataList* CDataManager::FindChartDataList(string a_Serial)
{
	mapChartDataListPos pos = ChartDataListMap.find(a_Serial);
	if (pos != ChartDataListMap.end())
	{
		return pos->second;
	}
	else
		return NULL;
}

ChartDataList* CDataManager::FindChartDataList(string a_Code, IChartDataType a_DataType, IChartBaseType a_BaseType, long a_Period)
{
	string mapKey = CSPUtil::MakeChartSerial(a_Code, a_DataType, a_BaseType, a_Period);
	return FindChartDataList(mapKey);
}

ChartDataList* CDataManager::FindChartDataList(ChartParam* a_Param)
{
	string mapKey = CSPUtil::MakeChartSerial(*a_Param);
	return FindChartDataList(mapKey);
}

void CDataManager::MakeNewDataList(string a_SrcKey, string a_Code, IChartDataType a_DataType, IChartBaseType a_BaseType, long a_Period, int a_MergeCount)
{
	if (a_MergeCount <= 1)
		return;

	ChartDataList* srcList = FindChartDataList(a_SrcKey);
	if (srcList != NULL)
	{
		string mapKey = CSPUtil::MakeChartSerial(a_Code, a_DataType, a_BaseType, a_Period * a_MergeCount);
		ChartDataList* dstList = AddChartDataList(mapKey);
		int cnt = 0;
		CChartData* newData = NULL;
		for (ChartDataListPos pos2 = srcList->begin(); pos2 != srcList->end(); ++pos2, cnt++)
		{
			CChartData* curData = *pos2;
			if (cnt % a_MergeCount == 0)
			{
				newData = curData->Clone();
				dstList->push_back(newData);
			}
			else
			{
				if (curData->H() > newData->H())
					newData->H(curData->H());
				if (curData->L() < newData->L())
					newData->L(curData->L());
				newData->C(curData->C());
				newData->AV(newData->AV() + curData->AV());
				newData->V(newData->V() + curData->V());
				newData->ET(curData->ET());
			}
		}
	}
}

void CDataManager::UpdateData(CChartData* a_CurData, int a_TotalCnt, string a_Code, IChartDataType a_DataType, IChartBaseType a_BaseType, long a_Period, int a_MergeCount)
{
	if (a_CurData == NULL)
		return;

	int cnt = a_TotalCnt - 1;
	size_t curCnt = (int)(a_TotalCnt / a_MergeCount);
	if (a_TotalCnt % a_MergeCount != 0)
		curCnt++;

	string mapKey = CSPUtil::MakeChartSerial(a_Code, a_DataType, a_BaseType, a_Period * a_MergeCount);
	ChartDataList* dstList = AddChartDataList(mapKey);
	CChartData* newData = NULL;
	if (curCnt > dstList->size())
	{
		newData = a_CurData->Clone();
		dstList->push_back(newData);
	}
	else
	{
		newData = dstList->back();
		if (a_CurData->H() > newData->H())
			newData->H(a_CurData->H());
		if (a_CurData->L() < newData->L())
			newData->L(a_CurData->L());
		newData->C(a_CurData->C());
		newData->AV(newData->AV() + a_CurData->AV());
		newData->V(newData->V() + a_CurData->V());
		newData->ET(a_CurData->ET());
	}
}

CChartMultiData* CDataManager::GetFirstDataList()
{
	mapChartMultiDataPos pos = ChartMD.begin();
	//pos++;
	return pos->second;
}

CSymbolInfo* CDataManager::GetFrontSymbol()
{
	SymbolInfoPos pos = SymbolMap.begin();
	if (pos != SymbolMap.end())
		return pos->second;
	else
		return NULL;
}

void CDataManager::AddRTChartTick(ChartTick* a_Tick)
{
	if (a_Tick && a_Tick->param)
	{
		CChartMultiData* pDList = FindChartMD(a_Tick->param);
		if (pDList)
		{
			long curDate = CSPUtil::GetToday();
			auto func = [&](string s)->long
			{
				long rTime = 0;
				string temp = s.substr(0, 2);
				rTime = _ttoi(temp.c_str()) * 10000;
				temp = s.substr(3, 2);
				rTime += _ttoi(temp.c_str()) * 100;
				temp = s.substr(6, 2);
				rTime += _ttoi(temp.c_str());
				return rTime;
			};
			long curTime = func(a_Tick->ST);
			pDList->AddData(curDate, curTime, a_Tick->C, a_Tick->C, a_Tick->C, a_Tick->C, (long)a_Tick->V);
			//AddBandData(pDList);
			//AddDayHighLow(pDList);
			//AddDayLimitData();
			InitSystemData();
		}
	}
}

void CDataManager::UpdateRTChartTick(ChartTick* a_Tick)
{
	if (a_Tick && a_Tick->param)
	{
		CChartMultiData* pDList = FindChartMD(a_Tick->param);
		if (pDList)
		{
			pDList->UpdateLastData(a_Tick->C, a_Tick->C, a_Tick->C, (long)a_Tick->V);
			//UpdateBandData(pDList);
			//UpdateDayHighLow(pDList);
			//UpdateDayLimitData();
			InitSystemData();
		}
	}
}

CSymbolInfo* CDataManager::GetSecondSymbol()
{
	SymbolInfoPos pos = SymbolMap.begin();
	pos++;
	if (pos != SymbolMap.end())
		return pos->second;
	else
		return NULL;
}

ChartDataList* CDataManager::AddRealTimeDataList(string a_Code)
{
	size_t size = RealTimeDataMap.size();
	if (size == 0)
	{
		ChartDataList* symInfo = new ChartDataList();
		RealTimeDataMap.insert(pairChartDataList(a_Code, symInfo));
		return symInfo;
	}
	else
	{
		mapChartDataListPos pos = RealTimeDataMap.find(a_Code);
		if (pos == RealTimeDataMap.end())
		{
			ChartDataList* symInfo = new ChartDataList();
			RealTimeDataMap.insert(pairChartDataList(a_Code, symInfo));
			return symInfo;
		}
		else
		{
			return pos->second;
		}
	}
}

void CDataManager::AddRealTimeData(CSymbolInfo* a_Sym)
{
	if (a_Sym)
	{
		int min = CSPUtil::GetTime(a_Sym->m_PriceInfo.ST, itrM);
		int sec = CSPUtil::GetTime(a_Sym->m_PriceInfo.ST, itrS);
		ChartDataList* pDList = GDataManager.AddRealTimeDataList(a_Sym->m_Code);
		CChartData* newData = NULL;
		if (pDList->size() > 0)
		{
			CChartData* curData = pDList->back();
			COleDateTime curTime = curData->Date();
			int newMin = CSPUtil::GetTime(a_Sym->m_PriceInfo.ST, itrM);
			if (newMin != curTime.GetMinute())
			{
				newData = new CChartData();
				newData->m_Date = CSPUtil::StringToDate(a_Sym->m_PriceInfo.ST);
				newData->m_C = a_Sym->m_PriceInfo.C;
				newData->m_L = a_Sym->m_PriceInfo.L;
				newData->m_O = a_Sym->m_PriceInfo.O;
				newData->m_H = a_Sym->m_PriceInfo.H;
				newData->m_V = a_Sym->m_PriceInfo.V;
				pDList->push_back(newData);
			}
			else
			{
				if (a_Sym->m_PriceInfo.L < curData->m_L)
					curData->m_L = a_Sym->m_PriceInfo.L;
				if (a_Sym->m_PriceInfo.H > curData->m_H)
					curData->m_H = a_Sym->m_PriceInfo.H;
				curData->m_C = a_Sym->m_PriceInfo.C;
				curData->m_V += a_Sym->m_PriceInfo.V;
			}
		}
		else
		{
			newData = new CChartData();
			newData->m_Date = CSPUtil::StringToDate(a_Sym->m_PriceInfo.ST);
			newData->m_C = a_Sym->m_PriceInfo.C;
			newData->m_L = a_Sym->m_PriceInfo.L;
			newData->m_O = a_Sym->m_PriceInfo.O;
			newData->m_H = a_Sym->m_PriceInfo.H;
			newData->m_V = a_Sym->m_PriceInfo.V;
			pDList->push_back(newData);
		}
	}
}

void CDataManager::FindOpList(string a_ATM, StringList& a_OutList)
{
	SymbolInfoPos pos = SymbolMap.find(a_ATM);
	pos--;
	pos--;
	pos--;
	for (int i = 0; i < 7; i++)
	{
		a_OutList.push_back(pos->first);
		pos++;
	}
}

CChartData* CDataManager::GetLastRealTimeData(CSymbolInfo* a_Sym)
{
	if (a_Sym)
	{
		string code = a_Sym->m_Code;
		mapChartDataListPos pos = RealTimeDataMap.find(code);
		if (pos != RealTimeDataMap.end())
		{
			ChartDataList* symInfo = pos->second;
			if (symInfo->size() > 0)
			{
				return symInfo->back();
			}
			else
				return NULL;
		}
		else
			return NULL;
	}
	return NULL;
}

CChartMultiData* CDataManager::AddChartMD(string a_Serial)
{
	size_t size = ChartMD.size();
	if (size == 0)
	{
		CChartMultiData* symInfo = new CChartMultiData();
		ChartMD.insert(pairChartMultiData(a_Serial, symInfo));
		return symInfo;
	}
	else
	{
		mapChartMultiDataPos pos = ChartMD.find(a_Serial);
		if (pos == ChartMD.end())
		{
			CChartMultiData* symInfo = new CChartMultiData();
			ChartMD.insert(pairChartMultiData(a_Serial, symInfo));
			return symInfo;
		}
		else
		{
			return pos->second;
		}
	}
}

CChartMultiData* CDataManager::FindChartMD(ChartParam* a_Param)
{
	string mapKey = CSPUtil::MakeChartSerial(*a_Param);
	return FindChartMD(mapKey);
}

CChartMultiData* CDataManager::FindChartMD(string a_Key)
{
	mapChartMultiDataPos pos = ChartMD.find(a_Key);
	if (pos != ChartMD.end())
		return pos->second;
	else
		return NULL;
}

CChartSingleData* CDataManager::AddChartSD(string a_Serial)
{
	size_t size = ChartSD.size();
	if (size == 0)
	{
		CChartSingleData* symInfo = new CChartSingleData();
		ChartSD.insert(pairChartSingleData(a_Serial, symInfo));
		return symInfo;
	}
	else
	{
		mapChartSingleDataPos pos = ChartSD.find(a_Serial);
		if (pos == ChartSD.end())
		{
			CChartSingleData* symInfo = new CChartSingleData();
			ChartSD.insert(pairChartSingleData(a_Serial, symInfo));
			return symInfo;
		}
		else
		{
			return pos->second;
		}
	}
}

CChartSingleData* CDataManager::FindChartSD(ChartParam* a_Param)
{
	string mapKey = CSPUtil::MakeChartSerial(*a_Param);
	return FindChartSD(mapKey);
}

CChartSingleData* CDataManager::FindChartSD(string a_Key)
{
	mapChartSingleDataPos pos = ChartSD.find(a_Key);
	if (pos != ChartSD.end())
		return pos->second;
	else
		return NULL;
}

void CDataManager::MakeBandData(CChartMultiData* a_MultiData)
{
	if (a_MultiData)
	{
		CChartSingleData* pJzHighH = GDataManager.AddChartSD(JZHH);
		CChartSingleData* pJzHighL= GDataManager.AddChartSD(JZHL);
		CChartSingleData* pJzLowH = GDataManager.AddChartSD(JZLH);
		CChartSingleData* pJzLowL = GDataManager.AddChartSD(JZLL);
		pJzHighH->Init(a_MultiData, a_MultiData->S + 30, a_MultiData->S + 30);
		pJzHighL->Init(a_MultiData, a_MultiData->S + 30, a_MultiData->S + 30);
		pJzLowH->Init(a_MultiData, a_MultiData->S + 30, a_MultiData->S + 30);
		pJzLowL->Init(a_MultiData, a_MultiData->S + 30, a_MultiData->S + 30);
		for (int i = a_MultiData->S + 30; i < a_MultiData->E; i++)
		{
			double max = *max_element(a_MultiData->High + i - 29, a_MultiData->High + i);
			double hh = max + 0.15;
			double hl = hh - 0.25;
			pJzHighH->AddData(a_MultiData->Date[i], a_MultiData->Time[i], hh);
			pJzHighL->AddData(a_MultiData->Date[i], a_MultiData->Time[i], hl);
			double min = *min_element(a_MultiData->Low + i - 29, a_MultiData->Low + i);
			double lh = min + 0.1;
			double ll = lh - 0.25;
			pJzLowH->AddData(a_MultiData->Date[i], a_MultiData->Time[i], lh);
			pJzLowL->AddData(a_MultiData->Date[i], a_MultiData->Time[i], ll);
		}
	}
}

void CDataManager::UpdateBandData(CChartMultiData* a_MultiData)
{
	if (a_MultiData)
	{
		CChartSingleData* pJzHighH = GDataManager.AddChartSD(JZHH);
		CChartSingleData* pJzHighL = GDataManager.AddChartSD(JZHL);
		CChartSingleData* pJzLowH = GDataManager.AddChartSD(JZLH);
		CChartSingleData* pJzLowL = GDataManager.AddChartSD(JZLL);
		int i = a_MultiData->E - 1;
		double max = *max_element(a_MultiData->High + i - 30, a_MultiData->High + i);
		double hh = max + 0.15;
		double hl = hh - 0.25;
		pJzHighH->SetData(i, a_MultiData->Date[i], a_MultiData->Time[i], hh);
		pJzHighL->SetData(i, a_MultiData->Date[i], a_MultiData->Time[i], hl);
		double min = *min_element(a_MultiData->Low + i - 30, a_MultiData->Low + i);
		double lh = min + 0.1;
		double ll = lh - 0.25;
		pJzLowH->SetData(i, a_MultiData->Date[i], a_MultiData->Time[i], lh);
		pJzLowL->SetData(i, a_MultiData->Date[i], a_MultiData->Time[i], ll);
	}
}

void CDataManager::AddBandData(CChartMultiData* a_MultiData)
{
	if (a_MultiData)
	{
		CChartSingleData* pJzHighH = GDataManager.AddChartSD(JZHH);
		CChartSingleData* pJzHighL = GDataManager.AddChartSD(JZHL);
		CChartSingleData* pJzLowH = GDataManager.AddChartSD(JZLH);
		CChartSingleData* pJzLowL = GDataManager.AddChartSD(JZLL);
		int i = a_MultiData->E - 1;
		double max = *max_element(a_MultiData->High + i - 30, a_MultiData->High + i);
		double hh = max + 0.15;
		double hl = hh - 0.25;
		pJzHighH->SetDataWithLastIndex(i, a_MultiData->Date[i], a_MultiData->Time[i], hh);
		pJzHighL->SetDataWithLastIndex(i, a_MultiData->Date[i], a_MultiData->Time[i], hl);
		double min = *min_element(a_MultiData->Low + i - 30, a_MultiData->Low + i);
		double lh = min + 0.1;
		double ll = lh - 0.25;
		pJzLowH->SetDataWithLastIndex(i, a_MultiData->Date[i], a_MultiData->Time[i], lh);
		pJzLowL->SetDataWithLastIndex(i, a_MultiData->Date[i], a_MultiData->Time[i], ll);
	}
}

void CDataManager::FindDayHighLow(CChartMultiData* a_MultiData)
{
	if (a_MultiData)
	{
		CChartSingleData* pDayH = GDataManager.AddChartSD(DH);
		CChartSingleData* pDayL = GDataManager.AddChartSD(DL);
		pDayH->Init(a_MultiData->S, a_MultiData->S);
		pDayL->Init(a_MultiData->S, a_MultiData->S);
		double high = a_MultiData->High[a_MultiData->S];
		double low = a_MultiData->Low[a_MultiData->S];
		CString msg;
		for (int i = a_MultiData->S; i < a_MultiData->E; i++)
		{
			if (i > a_MultiData->S &&
				a_MultiData->Date[i] != a_MultiData->Date[i - 1])
			{
				high = a_MultiData->High[i];
				low = a_MultiData->Low[i];
			}

			if (a_MultiData->Low[i] < low)
			{
				if (a_MultiData->Low[i] == 0)
					low = pDayL->D[max(0, i - 1)];
				else
					low = a_MultiData->Low[i];
			}


			if (a_MultiData->High[i] > high)
			{
				if (a_MultiData->High[i] == 0)
					high = pDayH->D[max(0, i - 1)];
				else
					high = a_MultiData->High[i];
			}
			msg.Format(_T("high = %.2f, low = %.2f \n"), high, low);
			OutputDebugString(msg);
			pDayL->AddData(a_MultiData->Date[i], a_MultiData->Time[i], low);
			pDayH->AddData(a_MultiData->Date[i], a_MultiData->Time[i], high);
		}
	}
}

void CDataManager::FindRegression(CChartMultiData* a_MultiData, int a_Len, string atm, int times)
{
	if (a_MultiData)
	{
		double out[MAX_COUNT];
		memset(out, 0x00, sizeof(out));
		int bi = 0, cnt = 0;
		TA_LINEARREG_SLOPE(a_MultiData->E - 10, a_MultiData->E - 1, a_MultiData->Close, 5, &bi, &cnt, out);
		int di = CSPUtil::GetDayIndex(a_MultiData->E - 1, a_MultiData);
		di++;
		bi++;
		cnt++;
	}
}

void CDataManager::MakeDayIndex(CChartMultiData* a_MultiData)
{
	if (a_MultiData)
	{
		int count = 0;
		if (a_MultiData == NULL)
			return;
		CChartSingleData* pDI = GDataManager.AddChartSD(DI);
		if (pDI)
		{
			long curDate = a_MultiData->Date[a_MultiData->S];
			long oldDate = curDate;
			for (int i = a_MultiData->S; i < a_MultiData->E; i++)
			{
				curDate = a_MultiData->Date[i];
				if (curDate != oldDate)
					count = 0;
				pDI->AddData(count++);
				oldDate = curDate;
			}
		}
	}
}


double CDataManager::MakeAveDayHeight(CChartMultiData* a_MultiData)
{
	if (!a_MultiData)
		return 0.0;
	double sum = 0;
	for (int i = a_MultiData->S; i < a_MultiData->E; i++)
	{
		double delta = abs(a_MultiData->High[i] - a_MultiData->Low[i]);
		sum += delta;
	}

	return sum / a_MultiData->E;
}

double CDataManager::MakeAveDayHeight(double& a_Min, double& a_Max, double& a_Avg)
{
	ChartParam param;
	param.ChartType = 'D';
	param.Code = CFCode;
	param.Count = 60;
	param.DataType = 0;
	param.EndDate = 99999999;
	param.Period = 1;
	param.RequestType = '2';
	param.StartDate = 99999999;
	string mapKey = CSPUtil::MakeChartSerial(param);
	CChartMultiData* a_MultiData = GDataManager.AddChartMD(mapKey);
	if (!a_MultiData)
		return -1.0;
	double sum = 0;
	double max = 0.0;
	double min = 99.0;
	for (int i = a_MultiData->S; i < a_MultiData->E; i++)
	{
		double delta = abs(a_MultiData->High[i] - a_MultiData->Low[i]);
		if (delta <= 1.0)
			continue;

		if (delta > max)
			max = delta;
		if (delta < min)
			min = delta;
		sum += delta;
	}

	a_Min = min;
	a_Max = max;

	sum -= max;
	sum -= min;
	a_Avg = sum / (a_MultiData->E - 2);

	MinHeight = min;
	MaxHeight = max;
	AvgHeight = a_Avg;

	return a_Avg;
}

void CDataManager::InitSystemData()
{
	ChartParam param;
	param.ChartType = 'T';
	param.Code = CFCode;
	param.Count = DefaultDataCount;
	param.DataType = 0;
	param.EndDate = 99999999;
	param.Period = MainCycle;
	param.RequestType = '2';
	param.StartDate = 99999999;

	string mapKey = CSPUtil::MakeChartSerial(param);
	CChartMultiData* a_MultiData = GDataManager.AddChartMD(mapKey);
	if (!a_MultiData)
		return;
	GDataManager.AddChartSD(_T("DayIndex"));
	GDataManager.MakeBandData(a_MultiData);
	GDataManager.FindDayHighLow(a_MultiData);
	GDataManager.FindDayLimitData();

	GSysManager.PreRun(a_MultiData);
}

void CDataManager::FindDayLimitData()
{
	CChartSingleData* pDH = GDataManager.FindChartSD(DH);
	CChartSingleData* pDL = GDataManager.FindChartSD(DL);
	double min = 0, max = 0, avg = 0;
	double result = MakeAveDayHeight(min, max, avg);
	if (pDH && pDL)
	{
		CChartSingleData* pULH = GDataManager.AddChartSD(ULH);
		CChartSingleData* pULL = GDataManager.AddChartSD(ULL);
		CChartSingleData* pBLH = GDataManager.AddChartSD(BLH);
		CChartSingleData* pBLL = GDataManager.AddChartSD(BLL);
		pULH->Init(pDH->S, pDH->S);
		pULL->Init(pDH->S, pDH->S);
		pBLH->Init(pDH->S, pDH->S);
		pBLL->Init(pDH->S, pDH->S);
		for (int i = pDH->S; i < pDH->E; i++)
		{
			pULL->AddData(pDH->Date[i], pDH->Time[i], pDL->D[i] + min);
			pULH->AddData(pDH->Date[i], pDH->Time[i], pDL->D[i] + avg);
			pBLH->AddData(pDH->Date[i], pDH->Time[i], pDH->D[i] - min);
			pBLL->AddData(pDH->Date[i], pDH->Time[i], pDH->D[i] - avg);
		}
	}
}

void CDataManager::UpdateDayHighLow(CChartMultiData* a_MultiData)
{
	if (!a_MultiData)
		return;

	CChartSingleData* pDayH = GDataManager.AddChartSD(DH);
	CChartSingleData* pDayL = GDataManager.AddChartSD(DL);
	int i = a_MultiData->E - 1;
	double high = pDayH->D[i - 1];
	double low = pDayL->D[i - 1];
	CString msg;
	if (i > a_MultiData->S &&
		a_MultiData->Date[i] != a_MultiData->Date[i - 1])
	{
		high = a_MultiData->High[i];
		low = a_MultiData->Low[i];
	}

	if (a_MultiData->Low[i] < low)
	{
		if (a_MultiData->Low[i] == 0)
			low = pDayL->D[max(0, i - 1)];
		else
			low = a_MultiData->Low[i];
	}


	if (a_MultiData->High[i] > high)
	{
		if (a_MultiData->High[i] == 0)
			high = pDayH->D[max(0, i - 1)];
		else
			high = a_MultiData->High[i];
	}
	msg.Format(_T("high = %.2f, low = %.2f \n"), high, low);
	OutputDebugString(msg);
	pDayL->SetData(i, a_MultiData->Date[i], a_MultiData->Time[i], low);
	pDayH->SetData(i, a_MultiData->Date[i], a_MultiData->Time[i], high);
}

void CDataManager::AddDayHighLow(CChartMultiData* a_MultiData)
{
	if (!a_MultiData)
		return;

	CChartSingleData* pDayH = GDataManager.AddChartSD(DH);
	CChartSingleData* pDayL = GDataManager.AddChartSD(DL);
	int i = a_MultiData->E - 1;
	double high = pDayH->D[i - 1];
	double low = pDayL->D[i - 1];
	CString msg;
	if (i > a_MultiData->S &&
		a_MultiData->Date[i] != a_MultiData->Date[i - 1])
	{
		high = a_MultiData->High[i];
		low = a_MultiData->Low[i];
	}

	if (a_MultiData->Low[i] < low)
	{
		if (a_MultiData->Low[i] == 0)
			low = pDayL->D[max(0, i - 1)];
		else
			low = a_MultiData->Low[i];
	}


	if (a_MultiData->High[i] > high)
	{
		if (a_MultiData->High[i] == 0)
			high = pDayH->D[max(0, i - 1)];
		else
			high = a_MultiData->High[i];
	}
	msg.Format(_T("high = %.2f, low = %.2f \n"), high, low);
	OutputDebugString(msg);
	pDayL->SetDataWithLastIndex(i, a_MultiData->Date[i], a_MultiData->Time[i], low);
	pDayH->SetDataWithLastIndex(i, a_MultiData->Date[i], a_MultiData->Time[i], high);
}

void CDataManager::UpdateDayLimitData()
{
	CChartSingleData* pDH = GDataManager.FindChartSD(DH);
	CChartSingleData* pDL = GDataManager.FindChartSD(DL);
	double min = 0, max = 0, avg = 0;
	double result = MakeAveDayHeight(min, max, avg);
	if (pDH && pDL)
	{
		CChartSingleData* pULH = GDataManager.AddChartSD(ULH);
		CChartSingleData* pULL = GDataManager.AddChartSD(ULL);
		CChartSingleData* pBLH = GDataManager.AddChartSD(BLH);
		CChartSingleData* pBLL = GDataManager.AddChartSD(BLL);
		int i = pDH->E - 1;
		pULL->SetData(i, pDH->Date[i], pDH->Time[i], pDL->D[i] + min);
		pULH->SetData(i, pDH->Date[i], pDH->Time[i], pDL->D[i] + avg);
		pBLH->SetData(i, pDH->Date[i], pDH->Time[i], pDH->D[i] - min);
		pBLL->SetData(i, pDH->Date[i], pDH->Time[i], pDH->D[i] - avg);
	}
}

void CDataManager::AddDayLimitData()
{
	CChartSingleData* pDH = GDataManager.FindChartSD(DH);
	CChartSingleData* pDL = GDataManager.FindChartSD(DL);
	double min = 0, max = 0, avg = 0;
	double result = MakeAveDayHeight(min, max, avg);
	if (pDH && pDL)
	{
		CChartSingleData* pULH = GDataManager.AddChartSD(ULH);
		CChartSingleData* pULL = GDataManager.AddChartSD(ULL);
		CChartSingleData* pBLH = GDataManager.AddChartSD(BLH);
		CChartSingleData* pBLL = GDataManager.AddChartSD(BLL);
		int i = pDH->E - 1;
		pULL->SetDataWithLastIndex(i, pDH->Date[i], pDH->Time[i], pDL->D[i] + min);
		pULH->SetDataWithLastIndex(i, pDH->Date[i], pDH->Time[i], pDL->D[i] + avg);
		pBLH->SetDataWithLastIndex(i, pDH->Date[i], pDH->Time[i], pDH->D[i] - min);
		pBLL->SetDataWithLastIndex(i, pDH->Date[i], pDH->Time[i], pDH->D[i] - avg);
	}
}

void CDataManager::MakeData()
{
	;
}
